﻿using System;
using System.Xml;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text;
using System.Drawing;
using Athena.Core;

namespace Athena.Objects
{
    [Serializable()]
    public class ModuleConnector : BezierConnector
    {
        Item _FromNode, _ToNode;
        /// <summary>
        /// maps item to target
        /// </summary>
        /// <param name="target">target</param>
        /// <param name="item">item</param>
        public ModuleConnector(IDrawable target, IDrawable item) 
        {
            if (target == null || target.Item == null || 
                item == null || item.Item == null ||
                item.Item.ParentModule == null || target.Item.ParentModule == null
                )
            {
                IsVisible = false;
                return;
            }

            if (item.Item.ParentModule.IsParentOf(target.Item))
            {
                IDrawable temp = item;
                item = target;
                target = temp;
            }

            int inputs = 1;
            List<IDrawable> list = new List<IDrawable>(2);
            list.Add(target);
            list.Add(item);

            MakeSegments(list, inputs);

            int i = 0;
            foreach (IDrawable it in list)
            {
                if (it is IGlyph) //inform the iglyph about its new connection
                {
                    if (i < inputs)
                        ((IGlyph)it).AddOutgoingConnection(this);    //input node
                    else
                        ((IGlyph)it).AddIncomingConnection(this);  //output node
                }
                ++i;
            }

            SetMapping(item, target);

            foreach (CurveSegment c in _CurveSegments)
            {
                c.ArrowHead = ArrowHeadType.Arrow;
                c.ArrowSize = 5;
            }

            _DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            _oFillColorStart = _oFillColorEnd = Color.OrangeRed;
            DoubleSelectedColor = SelectedColor;
            StraightLines = true;
            View = ViewType.Schematic;

            LoadDefaults(ModuleConnector.DEFAULT);
        }

        public static new ModuleConnector DEFAULT = null;

        public ModuleConnector()
        {
        }

        public override void WriteXML(XmlWriter writer)
        {
            _Item = new Edge();
            if (Parent != null)
                _Item.Parent = Parent.Item;
            else
                _Item.Parent = Program.Model.BackEndModel;

            base.WriteXML(writer);

            _Item.Remove();
            _Item = null;
        }

        public override bool ReadXML(System.Xml.XmlReader reader)
        {
            if (Parent != null)
            {
                _Item = new Edge();
                _Item.Parent = Parent.Item;

                base.ReadXML(reader);

                if (_CurveSegments != null && _CurveSegments.Count == 2)
                {
                    IDrawable t = _CurveSegments[0].StartNode,
                              i = _CurveSegments[1].StartNode;
                    SetMapping(i, t);
                }

                _Item.Remove();
                _Item = null;
            }
            return true;
        }

        public virtual void SetMapping(IDrawable item, IDrawable target)
        {
            if (target == null || target.Item == null ||
                item == null || item.Item == null ||
                item.Item.ParentModule == null || target.Item.ParentModule == null
                )
            {
                IsVisible = false;
                return;
            }

            if (item.Item.ParentModule.IsParentOf(target.Item))
            {
                IDrawable temp = item;
                item = target;
                target = temp;
            }

            Item i = item.Item, t = target.Item;

            _FromNode = i;
            _ToNode = t;

            Module _HostModule = i.ParentModule;
            Module _TargetModule = t.ParentModule;

            if (_HostModule != null && _TargetModule != null && _HostModule != _TargetModule)// && t.ParentModule.IsParentOf(_HostModule))
            {
                _HostModule.SetMapping(i, t);
            }
            if (_HostModule.GetMappingTo(i) != t)
            {
                IsVisible = false;
                Remove();
            }
            else
            {
                IGlyph node1 = item as IGlyph;
                if (node1 != null)
                {
                    for (int k = node1.IncomingConnections.Count - 1; k >= 0; --k)
                        if (node1.IncomingConnections[k] != this && node1.IncomingConnections[k] is ModuleConnector)
                            node1.IncomingConnections[k].Remove();
                }
            }
        }

        public override Item Item
        {
            get
            {
                return _Item;
            }
            set
            {   
            }
        }

        public override Connector.ArrowHeadType ArrowHead
        {
            get
            {
                return ArrowHeadType.None;
            }
            set
            {
            }
        }

        public override void AddAlias(IDrawable drawable)
        {            
        }

        public override IDrawable GenerateAlias()
        {
            return null;
        }

        public override void AddProduct(IDrawable item)
        {
        }

        public override void AddReactant(IDrawable item)
        {
        }

        public override void AddModifier(IDrawable item)
        {
        }

        public override void ChangeToModifiers()
        {
        }

        public override void ChangeToReactants()
        {
        }

        public override bool ShowMiddleSegment
        {
            get
            {
                return base.ShowMiddleSegment;
            }
            set
            {                
            }
        }

        public override void Remove()
        {
            base.Remove();
            if (_FromNode != null && _FromNode.ParentModule != null && 
                _FromNode.ParentModule.GetMappingTo(_FromNode) == _ToNode)
                _FromNode.ParentModule.SetMapping(_FromNode, null);
        }

        public override void ShowToolTip(ToolTip tooltip, Control pnlCanvas, PointF location)
        {
            if (_FromNode == null || _ToNode == null) return;
            tooltip.ToolTipTitle = "link two modules:";
            tooltip.SetToolTip(pnlCanvas,
                String.Format(
                            "{0} is the same as {1}",
                _FromNode.ID, _ToNode.ID));
        }
    }
}
